<html>
    <head>
        <title>应用服务示例</title>
    </head>
    <body>
        <script>
              /*
                        一、应用服务示例

                                1、假设有一个Book实体（实际上是一个聚合根）：

                                                public class Book : AggregateRoot<Guid>
                                                {
                                                    public const int MaxNameLength = 128;

                                                    public virtual string Name { get; protected set; }

                                                    public virtual BookType Type { get; set; }

                                                    public virtual float? Price { get; set; }

                                                    protected Book()
                                                    {
                                                        
                                                    }

                                                    public Book(Guid id, [NotNull] string name, BookType type, float? price = 0)
                                                    {
                                                        Id = id;
                                                        Name = CheckName(name);
                                                        Type = type;
                                                        Price = price;
                                                    }

                                                    // 与实体相关的业务逻辑
                                                    public virtual void ChangeName([NotNull] string name)
                                                    {
                                                        Name = CheckName(name);
                                                    }

                                                    // 与实体相关的业务逻辑
                                                    private static string CheckName(string name)
                                                    {
                                                        if (string.IsNullOrWhiteSpace(name))
                                                        {
                                                            throw new ArgumentException(
                                                                $"name can not be empty or white space!");
                                                        }

                                                        if (name.Length > MaxNameLength)
                                                        {
                                                            throw new ArgumentException(
                                                                $"name can not be longer than {MaxNameLength} chars!");
                                                        }

                                                        return name;
                                                    }
                                                }

                                                Book实体有一个MaxNameLength，它定义了Name属性的最大长度。

                                                Book构造函数和ChangeName方法以确保Name始终是一个有效值。请注意，Name的setter不是public。


                                                （ABP不会强迫你这样设计你的实体。它只是可以为所有属性提供公共get/set。是否完全实施DDD实践是你的决定。）



                                2、定义服务接口：  IBookService

                                                ABP中，应用程序服务应该实现IApplicationService接口。最好为每个应用程序服务创建一个接口：

                                                        public interface IBookAppService : IApplicationService
                                                        {
                                                            Task CreateAsync(CreateBookDto input);
                                                        }

                                                将实现一个Create方法作为示例。CreateBookDto是这样定义的：

                                                        public class CreateBookDto
                                                        {
                                                            [Required]
                                                            [StringLength(Book.MaxNameLength)]
                                                            public string Name { get; set; }

                                                            public BookType Type { get; set; }

                                                            public float? Price { get; set; }
                                                        }


                                3、定义服务实现：  BookAppService

                                                        public class BookAppService : ApplicationService, IBookAppService
                                                        {
                                                            private readonly IRepository<Book, Guid> _bookRepository;

                                                            public BookAppService(IRepository<Book, Guid> bookRepository)
                                                            {
                                                                _bookRepository = bookRepository;
                                                            }

                                                            public async Task CreateAsync(CreateBookDto input)
                                                            {
                                                                var book = new Book(
                                                                    GuidGenerator.Create(),
                                                                    input.Name,
                                                                    input.Type,
                                                                    input.Price
                                                                );

                                                                await _bookRepository.InsertAsync(book);
                                                            }
                                                        }

                                                    BookAppService继承自ApplicationService基类。
                                                    
                                                    它不是必需的，但是ApplicationService类为常见的应用程序服务需求提供了有用的属性，例如此服务中使用的GuidGenerator。

                                                    如果我们没有继承它，我们需要手动注入IGuidGenerator服务（请参阅guid生成文档）。

                                                    BookAppService按预期实现了IBookAppService。

                                                    BookAppService注入IRepository<Book, Guid>（请参阅存储库）并在CreateAsync方法中使用它将新实体插入数据库。

                                                    CreateAsync使用Book实体的构造函数根据给定input的属性创建一本新书。

                    */

        </script>
    </body>
</html>